package com.ysl.netty.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


public class TcpManyClient {
    //多个tcp服务器的端口
    private static List<Integer> PORTS = Arrays.asList(20000, 20001, 20002, 20003, 20004);
    //多个tcp服务器的ip
    private static List<String> HOSTS = Arrays.asList("127.0.0.1", "127.0.0.1", "127.0.0.1", "127.0.0.1", "127.0.0.1");
    public static Map<Integer, ChannelFuture> channels = getChannel(HOSTS, PORTS);

    /**
     * 初始化Bootstrap
     */
    public static final Bootstrap getBootstrap(EventLoopGroup group) {
        if (null == group) {
            group = new NioEventLoopGroup();
        }
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group).channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.SO_KEEPALIVE, true);
        bootstrap.handler(new ChannelInitializer<Channel>() {
            @Override
            protected void initChannel(Channel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                // 添加自定义协议的编解码工具
                pipeline.addLast(new IdleStateHandler(0, 30, 0, TimeUnit.SECONDS));
                //ch.pipeline().addLast(new SmartCarEncoder());
                //ch.pipeline().addLast(new SmartCarDecoder());
                pipeline.addLast(new TcpClientHandler());
            }
        });
        return bootstrap;
    }

    //   获取所有连接
    public static final Map<Integer, ChannelFuture> getChannel(List<String> hosts, List<Integer> ports) {
        Map<Integer, ChannelFuture> result = new HashMap<>();
        Bootstrap bootstrap = getBootstrap(null);
        for (int i = 0; i < hosts.size(); i++) {
            String host = hosts.get(i);
            int port = ports.get(i);
            bootstrap.remoteAddress(host, port);
            //异步连接tcp服务端
            ChannelFuture future = bootstrap.connect().addListener((ChannelFuture futureListener) -> {
                final EventLoop eventLoop = futureListener.channel().eventLoop();
                if (!futureListener.isSuccess()) {
                    //服务器未启动 连接tcp服务器不成功
                    System.out.println(port + "第一次连接与服务端断开连接!在10s之后准备尝试重连!");
                    //10秒后重连
                    eventLoop.schedule(() -> doConnect(bootstrap, host, port), 10, TimeUnit.SECONDS);
                }
            });
            result.put(port, future);
        }
        return result;
    }

    /**
     * 重新连接tcp服务端
     */
    public static void doConnect(Bootstrap bootstrap , String host, int port) {
        try {
            if (bootstrap != null) {
                //
                bootstrap.remoteAddress(host, port);
                ChannelFuture f = bootstrap.connect().addListener((ChannelFuture futureListener) -> {
                    final EventLoop eventLoop = futureListener.channel().eventLoop();
                    if (!futureListener.isSuccess()) {
                        //连接tcp服务器不成功 10后重连
                        System.out.println(port + "服务器断线-----与服务端断开连接!在10s之后准备尝试重连!");
                        eventLoop.schedule(() -> doConnect(bootstrap, host, port), 10, TimeUnit.SECONDS);
                    }
                });
                channels.put(port, f);
            }
        } catch (Exception e) {
            System.out.println("客户端连接失败!" + e.getMessage());
        }

    }
    //发送消息
    public void sendMsg(ChannelFuture future, String msg) throws Exception {
        if (future != null && future.channel().isActive()) {
            // 发送SmartCar协议的消息
            // 要发送的信息
            // 获得要发送信息的字节数组
            byte[] content = msg.getBytes();
            // 要发送信息的长度
            int contentLength = content.length;
            Channel channel = future.channel();
            InetSocketAddress ipSocket = (InetSocketAddress) channel.remoteAddress();
            int port = ipSocket.getPort();
            String host = ipSocket.getHostString();
            //SmartCarProtocol protocol = new SmartCarProtocol(contentLength, content);
            System.out.println("向服务端发消息" + port);
            //channel.writeAndFlush(protocol).sync();
        } else {
            System.out.println("消息发送失败,连接尚未建立!");
        }
    }

}
